package com.chinatelecom.auth.mockmvc;

import com.chinatelecom.auth.mockmvc.inter.AuthMockMvcInterface;
import com.chinatelecom.auth.mockmvc.inter.BuilderInterface;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;

import java.util.Map;

/**
 * Created by liujinyao on 2017/7/27.
 */
public class AuthMockMvc implements AuthMockMvcInterface {

    private AuthDetail beforePrepare;
    private AuthDetail afterPrepare;
    private MockMvc mockMvc;

    private AuthHttpRequest request = new AuthHttpRequest();
    private AuthHttpResponse response = new AuthHttpResponse();

    public void run() throws Exception{
        preMock();
        mock();
        afterMock();
    }

    public AuthMockMvc(Builder builder){
        this.beforePrepare = builder.beforePrepare;
        this.afterPrepare = builder.afterPrepare;
        this.mockMvc = builder.mockMvc;
    }

    @Override
    public void preMock() {
        if(beforePrepare==null){
            return;
        }

        beforePrepare.run();
    }

    @Override
    public void mock() throws Exception{
        switch (request.method){
            case "post":
                postMethod(request);
                break;
            default:
                postMethod(request);
        }
    }

    private void postMethod(AuthHttpRequest request) throws Exception{
        try{
            MockHttpServletRequestBuilder requestBuilder = post(request.uri).contentType(MediaType.APPLICATION_JSON).content(request.content);
            //设置头部
            for(Map.Entry<String,String> entry : request.headers.entrySet()){
                requestBuilder.header(entry.getKey(),entry.getValue());
            }
            MockHttpServletResponse mockResponse = mockMvc.perform(requestBuilder).andReturn().getResponse();

            response.status = status(mockResponse.getStatus());
            response.content = mockResponse.getContentAsString();
        }catch(Exception e){
            throw e;
        }
    }

    public HttpStatus status(Integer status){
        switch(status) {
            case 200:
                return HttpStatus.OK;
            default:
                return HttpStatus.OK;
        }
    }

    @Override
    public void afterMock() {
        if(afterPrepare==null){
            return;
        }

        afterPrepare.run();
    }

    public AuthMockMvc setRequest(AuthHttpRequest request){
        this.request = request;
        return this;
    }

    public AuthHttpResponse response(){
        return this.response;
    }

    public static class Builder implements BuilderInterface<AuthMockMvc> {

        private AuthDetail beforePrepare;
        private AuthDetail afterPrepare;
        private MockMvc mockMvc;

        @Override
        public AuthMockMvc build() {
            return new AuthMockMvc(this);
        }

        public Builder beforePrepare(AuthDetail beforePrepare){
            this.beforePrepare = beforePrepare;
            return this;
        }

        public Builder afterPrepare(AuthDetail afterPrepare){
            this.afterPrepare = afterPrepare;
            return this;
        }

        public Builder mockMvc(MockMvc mockMvc){
            this.mockMvc = mockMvc;
            return this;
        }
    }
}
